/*
 *  chapter_12.cpp
 *
 *  Created on: 2020年11月27日
 *      Author: san
 */
#include <QueryResult.h.back>
#include <iostream>
#include <algorithm>
#include <fstream>
#include <cstring>

#include "Sales_data.h"
#include "StrBlobPtr.h"
#include "TextQuery.h"

Sales_data sd1;
void testBlod()
{
	Sales_data sd2("Y0001");
	sd1 = sd2;
}  // sd1所指向的内存已经被释放；

//std::cout << "sd1: " << sd1.isbn() << std::endl;

void t12_1()
{
	Sales_data sd1("Y0001");
	{
		Sales_data sd2("Y0002");
		sd1 = sd2;
	}
	std::cout << "sd1: " << sd1.isbn() << std::endl;
//	std::cout << "sd2: " << sd2.isbn() << std::endl;  // 不在作用域内
}


std::vector<int> *getApplicateVector()
{
	return new (std::nothrow) std::vector<int>();
}

void readToVector(std::vector<int> &ivec)
{
	int i;
	while (std::cin >> i)
	{
		ivec.push_back(i);
	}
}

void t12_6()
{
	std::vector<int> *ivec = getApplicateVector();
	readToVector(*ivec);
	std::for_each(ivec->begin(), ivec->end(), [](const int &i){ std::cout << i << " ";});
	delete ivec;  // 一定要记得delete

	std::cout << std::endl;
}

void t12_17()
{
	// 报错，智能指针不能赋值和拷贝
//	std::unique_ptr<string> usptr = "nihao";

	typedef std::unique_ptr<int> IntP;
	int ix = 1024, *pi = &ix, *pi2 = new int(2048);
//	IntP p0(ix);
//	IntP p1(pi);  // 非动态分配内存的普通指针初始化智能指针，在超出作用域后需要delete时报运行时异常
//	IntP p2(pi2);  // 动态分配内存的普通指针初始化，会存在悬浮指针问题， 并且好像程序也会异常终止
//	IntP p3(&ix);  // 同上上
	IntP p4(new int(2048));  // 合法， 推荐
//	IntP p5(p2.get());  // 编译不通过, p2释放, p5也可以释放,会造成两次delete

}

void t12_20()
{
	/*
	 * 从文件中读取string存入StrBlob中
	 */
	StrBlob sb;
	StrBlobPtr psb(sb);
	std::ifstream ifo("/home/san/eclipse-workspace/CppPrimer/file/input.txt");
	string word;
	while (ifo >> word)
	{
		sb.push_back(word);
	}

//	StrBlobPtr psb(sb);
	while (psb.getCurr() != sb.size())
	{
		std::cout << psb.deref() << " ";
		psb.incr();
	}
}

void connectChar()
{
	char* s1 = "hello";  // l1 = 5
	char* s2 = " world!";  // l2 = 7

	int l1 = strlen(s1);
	int l2 = strlen(s2);
//	char *p = new char[l1 + l2 + 1];  // 这里中括号中是size
	char *p = new char[0];
//	char *p = (char *)malloc((l1 + l2 + 1) * sizeof(char));

	std::cout << "l1: " << l1 << " l2: " << l2 << std::endl;

	strcat(p, s1);
	strcat(p, s2);

	std::cout << p << std::endl;

	// 一定要记得delete
//	delete [] p;
}

void t12_23()
{

	connectChar();
}

void t12_24()
{
    string str;

    std::cout << "Please input a string: ";
    std::getline(std::cin, str);

    char* cArray = new char[str.size()+1]();
    strcat(cArray, str.c_str());

    std::cout << cArray << std::endl;

    // 一定要记得delete
    delete[] cArray;
}

void t12_26()
{
	// 构建alloc对象
	std::allocator<string> alloc;

	// 分配n个未初始化的string
	auto const p = alloc.allocate(10);

	string *q = p;
	string s;
	while (std::cin >> s && q != p + 10)
	{
		alloc.construct(q++, s);
	}

	q = p;

	while (q != p + 10)
	{
		std::cout << *q++ << " ";
	}
}

void t12_29()
{
	/*
	 * 查询单词出现次数
	 */
	using QueryResult = TextQuery::QueryResult;
	string word;
	std::ifstream infile("/home/san/eclipse-workspace/CppPrimer/file/alibaba.txt");
	std::cout << "请输入需要查询的单词：" << std::endl;
	TextQuery tq(infile);
	while (std::cin >> word && "0" != word)
	{
		QueryResult result = tq.query(word);
		print(std::cout, result);
	}
}


int main12()
{

	std::cout << "-------------------当某个对象被销毁时，不能单方面的删除底层数据-------------------" << std::endl;
	std::cout << "sd1: " << sd1.isbn() << std::endl;

	// 静态代码块
	t12_1();

	std::cout << "-------------------直接管理内存-------------------" << std::endl;
//	t12_6();

	std::cout << "--------------------不要混用智能指针和普通指针---------------" << std::endl;
//	t12_17();

	std::cout << "------------弱指针------------------" << std::endl;
	t12_20();

	std::cout << "------------动态数组------------------" << std::endl;
	t12_23();
	std::cout << std::endl;

//	t12_24();

	std::cout << "------------allocator类------------------" << std::endl;
	/*
	 * new将分配对象、构造对象；delete将对象析构、内存释放绑定在一起了（这样会造成不必要的浪费）
	 * allocator 将其分离
	 */

//	t12_26();

	t12_29();


	std::cout << std::endl << "hello cpp" << std::endl;
	return 0;
}


